#include "../../core/base/file_io.h"
#include <stdio.h>
#include <stdlib.h>

struct FILE_HOLDER {
	FILE* pFile;
	unsigned int size;
	void* pFileData;
	FILE_HOLDER() {pFile = NULL; pFileData = NULL;}
};

KFileReader::KFileReader()
{
	mpFileDesc = new FILE_HOLDER;
}

KFileReader::KFileReader(const char* filename)
{
	mpFileDesc = new FILE_HOLDER;
	OpenFile(filename);
}

KFileReader::~KFileReader()
{
	CloseFile();
	ReleaseCopyInMemory();
	FILE_HOLDER* pFileHolder = (FILE_HOLDER*)mpFileDesc;
	delete pFileHolder;
}

bool KFileReader::OpenFile(const char* filename)
{
	FILE_HOLDER* pFileHolder = (FILE_HOLDER*)mpFileDesc;
	if (pFileHolder->pFile)
		CloseFile();
	pFileHolder->pFile = fopen(filename, "rb");
	if (pFileHolder->pFile == NULL)
		return false;
		
	fseek(pFileHolder->pFile, 0, SEEK_END);
	pFileHolder->size = ftell(pFileHolder->pFile);
	fseek(pFileHolder->pFile, 0, SEEK_SET);
	return true;
}

void KFileReader::CloseFile()
{
	FILE_HOLDER* pFileHolder = (FILE_HOLDER*)mpFileDesc;
	if (pFileHolder->pFile == NULL) {
		fclose(pFileHolder->pFile);
		pFileHolder->pFile = NULL;
	}
}

bool KFileReader::IsFileOpen() const
{
	FILE_HOLDER* pFileHolder = (FILE_HOLDER*)mpFileDesc;
	return pFileHolder->pFile != NULL;
}

bool KFileReader::Read(void* pOutData, unsigned int size)
{
	FILE_HOLDER* pFileHolder = (FILE_HOLDER*)mpFileDesc;
	if (NULL == pFileHolder->pFile)
		return false;
	return size == fread(pOutData, 1, size, pFileHolder->pFile);
}

bool KFileReader::Skip(unsigned int size)
{
	FILE_HOLDER* pFileHolder = (FILE_HOLDER*)mpFileDesc;
	if (NULL == pFileHolder->pFile)
		return false;
	return (fseek(pFileHolder->pFile, size, SEEK_CUR) == 0);
}

void KFileReader::ResetRead()
{
	FILE_HOLDER* pFileHolder = (FILE_HOLDER*)mpFileDesc;
	fseek(pFileHolder->pFile, 0, SEEK_SET);
}

unsigned int KFileReader::GetFileSize() const
{
	FILE_HOLDER* pFileHolder = (FILE_HOLDER*)mpFileDesc;
	return pFileHolder->size;
}

void* KFileReader::CopyIntoMemory()
{
	FILE_HOLDER* pFileHolder = (FILE_HOLDER*)mpFileDesc;
	if (pFileHolder->pFileData)
		free(pFileHolder->pFileData);
	unsigned int pos = ftell(pFileHolder->pFile);
	fseek(pFileHolder->pFile, 0, SEEK_SET);
	pFileHolder->pFileData = malloc(pFileHolder->size);
	fread(pFileHolder->pFileData, 1, pFileHolder->size, pFileHolder->pFile);
	fseek(pFileHolder->pFile, pos, SEEK_SET);
	return pFileHolder->pFileData;
}
void KFileReader::ReleaseCopyInMemory()
{
	FILE_HOLDER* pFileHolder = (FILE_HOLDER*)mpFileDesc;
	if (pFileHolder->pFileData)
		free(pFileHolder->pFileData);
	pFileHolder->pFileData = NULL;
}